package com.video.tool;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class VideoGifOverlay {
    private static final int GIF_HEIGHT = 30; // GIF高度

    public static void main(String[] args) {
        String inputVideo = "input.mp4";
        String outputVideo = "output.mp4";
        String gifPath = "animation.gif";

        try {
            addGifToVideo(inputVideo, outputVideo, gifPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void addGifToVideo(String inputVideo, String outputVideo, String gifPath) throws Exception {
        List<BufferedImage> gifFrames = readGifFrames(gifPath);
        if (gifFrames.isEmpty()) {
            throw new RuntimeException("无法读取GIF文件");
        }

        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideo);
        grabber.start();

        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputVideo,
                grabber.getImageWidth(),
                grabber.getImageHeight());

        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.setVideoBitrate(grabber.getVideoBitrate());
        recorder.start();

        int totalFrames = grabber.getLengthInFrames();
        Java2DFrameConverter converter = new Java2DFrameConverter();
        int currentGifFrame = 0;

        for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
            Frame frame = grabber.grab();
            if (frame == null || frame.image == null) {
                continue;
            }

            BufferedImage bufferedImage = converter.convert(frame);
            Graphics2D g2d = bufferedImage.createGraphics();

            BufferedImage gifFrame = gifFrames.get(currentGifFrame % gifFrames.size());
            int gifWidth = (int) ((double) GIF_HEIGHT / gifFrame.getHeight() * gifFrame.getWidth());

            double progress = (double) frameIndex / totalFrames;
            int x = (int) (progress * (bufferedImage.getWidth() - gifWidth));
            int y = bufferedImage.getHeight() - GIF_HEIGHT;

            g2d.drawImage(gifFrame, x, y, gifWidth, GIF_HEIGHT, null);
            g2d.dispose();

            // 将处理后的帧写入输出视频
            Frame processedFrame = converter.convert(bufferedImage);
            recorder.record(processedFrame);

            currentGifFrame++;
        }

        // 清理资源
        grabber.stop();
        grabber.release();
        recorder.stop();
        recorder.release();
    }

    private static List<BufferedImage> readGifFrames(String gifPath) throws Exception {
        List<BufferedImage> frames = new ArrayList<>();

        ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next();
        ImageInputStream stream = ImageIO.createImageInputStream(new File(gifPath));
        reader.setInput(stream);

        int count = reader.getNumImages(true);
        for (int i = 0; i < count; i++) {
            BufferedImage frame = reader.read(i);
            frames.add(frame);
        }

        reader.dispose();
        stream.close();

        return frames;
    }
}